/* **********************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This source code is subject to terms and conditions of the Shared Source License
* for DSL Editor PowerToy. A copy of the license can be found in the License.htm file
* at the root of this distribution. If you can not locate the Shared Source License
* for DSL Editor PowerToy, please obtain a copy from: http://www.codeplex.com/dsltreegrideditor/Project/License.aspx.
* By using this source code in any fashion, you are agreeing to be bound by
* the terms of the Shared Source License for DSL Editor PowerToy.
*
* You must not remove this notice, or any other, from this software.
*
* **********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Forms;

using VSTrid = Microsoft.VisualStudio.VirtualTreeGrid;
using Microsoft.VisualStudio.Modeling;

using DslEditorPowerToy.Controls.VirtualTreeGrid.Branches;

using DslEditorPowerToy.Controls.Editors.Special.DomainModelTreeGrid.Data;

namespace DslEditorPowerToy.Controls.Editors.Special.DomainModelTreeGrid.Branches
{
    /// <summary>
    /// Provides a branch that manipulates a domain model
    /// This branch adds and manages a single row for the domain model
    /// Row has static label as identifier (first column)
    /// </summary>
    internal class DomainModelBranch : DomainElementBranch
    {
        #region Constructors
        public DomainModelBranch(DomainModelTreeGridControl treeControl, IDomainModel branchData)
            : base(treeControl, branchData, typeof(object))
        {
        }
        #endregion

        #region Protected Properties
        /// <summary>
        /// Returns the data the branch is manipulating
        /// </summary>
        protected new internal IDomainModel BranchData
        {
            get
            {
                return base.BranchData as IDomainModel;
            }
        }
        #endregion

        #region IBranch Members

        /// <summary>
        /// Return the count of visible items in this navigationBranch.
        /// </summary>
        /// <value></value>
        public override int VisibleItemCount
        {
            get
            {
                return 1;
            }
        }
        /// <summary>
        /// Return the features supported by this navigationBranch.
        /// </summary>
        /// <value></value>
        public override VSTrid.BranchFeatures Features
        {
            get
            {
                return base.Features |
                    VSTrid.BranchFeatures.ImmediateMouseLabelEdits |
                    VSTrid.BranchFeatures.ExplicitLabelEdits |
                    VSTrid.BranchFeatures.Realigns |
                    VSTrid.BranchFeatures.InsertsAndDeletes |
                    VSTrid.BranchFeatures.JaggedColumns |
                    VSTrid.BranchFeatures.PositionTracking;
            }
        }
        /// <summary>
        /// Returns whether to allow expansion of row
        /// </summary>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public override bool IsExpandable(int row, int column)
        {
            return (0 == row) ? false : base.IsExpandable(row, column);
        }

        /// <summary>
        /// Locates specified object in branch
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="style"></param>
        /// <param name="locateOptions"></param>
        /// <returns></returns>
        public override VSTrid.LocateObjectData LocateObject(object obj, VSTrid.ObjectStyle style, int locateOptions)
        {
            switch (style)
            {
                case VSTrid.ObjectStyle.TrackingObject:
                    //Since we only have one item in this branch
                    if (obj is int)
                        return new VSTrid.LocateObjectData((int)obj, 0, (int)VSTrid.TrackingObjectAction.ThisLevel);
                    //Assume only one item of this type in branch
                    if (obj is IDomainModel)
                        return new VSTrid.LocateObjectData(0, 0, (int)VSTrid.TrackingObjectAction.ThisLevel);
                    else if ((obj is IDomainRelationship)
                        || (obj is IDomainClass))
                        return new VSTrid.LocateObjectData(0, 0, (int)VSTrid.TrackingObjectAction.NextLevel);
                    
                    return new VSTrid.LocateObjectData(0, 0, (int)VSTrid.TrackingObjectAction.NotTracked);

                default:
                    break;
            }

            return base.LocateObject(obj, style, locateOptions);
        }
        /// <summary>
        /// Returns the object at specified position and type
        /// </summary>
        /// <param name="row"></param>
        /// <param name="cellColumnIndex"></param>
        /// <param name="style"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override object GetObject(int row, int column, VSTrid.ObjectStyle style, ref int options)
        {
            switch (style)
            {
                case VSTrid.ObjectStyle.ExpandedBranch:
                    if ((null != this.BranchData.RelationshipType)
                        && (null != this.BranchData.ChildRelationships))
                        return new DomainClassBranch(base.TreeControl, ((IDomainClass)this.BranchData), this.BranchData.RelationshipType);
                    else
                        return null;

                case VSTrid.ObjectStyle.TrackingObject:
                    //Only want to track the row (and ignore the column)
                    //Since we only have one item in this branch
                    return this.BranchData;

                default:
                    return null;
            }
        }
        /// <summary>
        /// Returns the text for the specified cell
        /// </summary>
        /// <param name="row"></param>
        /// <param name="cellColumnIndex"></param>
        /// <returns></returns>
        public override string GetText(int row, int column)
        {
            if (0 == column)
            {
                //Display static data for first column
                if (false == string.IsNullOrEmpty(this.BranchData.DisplayName))
                    return string.Format("{0} - [{1}]", this.BranchData.DisplayName,
                        this.BranchData.Name);
                else
                    return string.Format("[{0}]", this.BranchData.Name);
            }
            else
            {
                //Shift column data over
                return base.GetText(row, (column - 1));
            }
        }
        public override VSTrid.VirtualTreeLabelEditData BeginLabelEdit(int row, int column, VSTrid.VirtualTreeLabelEditActivationStyles activationStyle)
        {
            //Prevent editing of first column
            if (0 == column)
                return VSTrid.VirtualTreeLabelEditData.Invalid;
            else
            {
                //shift column over
                return base.BeginLabelEdit(row, (column - 1), activationStyle);
            }
        }
        public override Microsoft.VisualStudio.VirtualTreeGrid.LabelEditResult CommitLabelEdit(int row, int column, string newText)
        {
            //shift column over
            return base.CommitLabelEdit(row, (column - 1), newText);
        }
        public override int ColumnCount
        {
            get
            {
                //Add label column at start
                return (base.ColumnCount + 1);
            }
        }
        #endregion

        #region BranchBase Members
        protected override short GetDataItemImageIndex(int row, int column)
        {
            if (0 == column)
                return BranchItemGlyphs.DomainModel;
            else
                return -1;
        }
        #endregion

        #region DomainElementBranch Methods
        /// <summary>
        /// Returns the dataItem for specified row
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        protected override IDomainElement GetElementAtRow(int row)
        {
            return this.BranchData;
        }
        /// <summary>
        /// Returns the row dataItem for this branch
        /// </summary>
        /// <returns></returns>
        protected override DomainElementCollection<IDomainElement> GetElementRows()
        {
            return null;
        }
        #endregion
    }
}
